# coding:utf-8
from . import api
from flask import request,jsonify,current_app,session
from ihome import redis_store,db
from ihome.models import User
from ihome.utils.response_code import RET
from sqlalchemy.exc import IntegrityError # 重复异常
from ihome import constants
from werkzeug import generate_password_hash,check_password_hash
import re

@api.route('/users',methods=['POST'])
def register():
    """注册
    请求参数： 手机号，短信验证码，密码，确认密码
    参数格式：json
    """
    # 获取请求的json数据，返回字典
    req_dict = request.get_json()

    mobile = req_dict.get("mobile")
    sms_code = req_dict.get('sms_code')
    password = req_dict.get("password")
    password2 = req_dict.get("password2")

    # 校验参数
    if not all([mobile, sms_code, password, password2]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")

    # 判断手机格式
    if not re.match(r"1[34578]\d{9}",mobile):  # 利用正则判断手机格式
        # 表示格式不正确
        return jsonify(errno=RET.PARAMERR,errmsg='手机格式不正确')

    # 判断两次输入两次密码是否一致
    if password != password2:
        return jsonify(errno=RET.PARAMERR,errmsg="两次密码不一致")

    # 从redis 中取出短信验证码：
    try:
        real_sms_code = redis_store.get("sms_code_%s" % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='读取真实短信验证码异常')

    # 判断短信验证码是否过期（意味着redis数据库中没有数据，查出来为None）
    if real_sms_code is None:
        return jsonify(errno=RET.NODATA,errmsg='短信验证码失效')

    # 删除redis中的短信验证码，防止重复使用校验
    try:
        redis_store.delete('sms_code_%s' %mobile)
    except Exception as e:
        current_app.logger.error(e)

    # 判断用户填写短信验证码的正确性
    if real_sms_code != sms_code:
        return jsonify(errno=RET.DBERR,errmsg="短信验证码错误")

    # 判断用户的手机号是否注册过
    # try:
    #     mobile设置了唯一性，重复会报错
    #     user = User.query.filter_by(mobile=mobile).first()
    # except Exception as e:
    #     current_app.logger.error(e)
    #     return jsonify(errno=RET.DBERR, errmsg="数据库异常")
    # else:
    #     if user is not None:
    #         # 表示手机号已存在
    #         return jsonify(errno=RET.DATAEXIST, errmsg="手机号已存在")

    # 盐值   salt

    #  注册
    #  用户1   password="123456" + "abc"   sha1   abc$hxosifodfdoshfosdhfso
    #  用户2   password="123456" + "def"   sha1   def$dfhsoicoshdoshfosidfs
    #
    # 用户登录  password ="123456"  "abc"  sha256      sha1   hxosufodsofdihsofho

    # 保存用户的注册数据到数据库中
    user = User(name=mobile,mobile=mobile)
    # user.generate_password_hash(password)
    # user.password_hash(password)

    user.password = password  # 设置属性

    try:
        db.session.add(user)
        db.session.commit()
    except IntegrityError as e:
        # 数据库出行异常之后的回滚
        db.session.rollback()
        # 表示手机号码重复了，（手机已经注册过了）
        current_app.logger(e)
    except Exception as e:
        # 数据库出行异常之后的回滚
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg="查询数据库异常")

    # 保存得登录状态到session中
    session['name'] = 'mobile'
    session['mobile'] = 'mobile'
    session['user_id'] = "user_id"

    # 返回结果
    return jsonify(errno=RET.OK,errmsg="注册成功")



@api.route('/sessions',methods=["POST"])
def login():
    """用户登录
    参数： 手机号，密码，
    格式：json
    """
    # 获取参数
    req_dict = request.get_json()

    mobile = req_dict.get("mobile")
    password = req_dict.get("password")

    # 检验参数
    # 检验参数的完整性
    if not all([mobile,password]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数不完整')

    # 检验是手机格式
    if not re.match(r"1[134578]\d{9}",mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手机格式不正确')

    # 判断错误次数是否超过限制，如果超过限制，则返回
    # redis记录： “access_nums_请求的ip":”次数“
    user_ip = request.remote_addr  # 用户的ip地址
    try:
        access_num = redis_store.get("access_num_%s" %user_ip)  # 取出记录错误的次数 ，没有就为None
    except Exception as e:
        current_app.logger.err(e)
    else:
        if access_num is not None and int(access_num) >= constants.LOGIN_ERROR_MAX_TIMES:
            return jsonify(errno=RET.REQERR,errmsg="错误次数过多，请稍候重试")

    # 从数据库中根据手机号码查询用户的数据对象
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg="获取用户信息失败")

    # 用 用户密码和数据库的密码进行对比验证
    if user is None or not user.check_password(password):
        # 如果检验失败，记录错误次数，返回信息
        try:
            # redis 的incr 可以对字符串类型的数据进行+1的操作，如果数据一开始不存在，则初始化为0
            redis_store.incr("access_num_%s" %user_ip)
            redis_store.expire("access_num%s" %user_ip,constants.LOGIN_ERROR_FORBID_TIME)
        except Exception as e:
            current_app.logger.error(e)

        return jsonify(errno=RET.DATAERR,errmsg="用户名或密码错误")

  # 如果验证相同成功，保存登录状态， 在session中
    session["name"] = user.name
    session["mobile"] = user.mobile
    session["user_id"] = user.id

    return jsonify(errno=RET.OK, errmsg="登录成功")

@api.route("/session",methods=["GET"])
def check_login():
    """检查登录状态"""
    # 尝试从session中获取用户名字
    name = session.get("name")
    # 如果session中数据name名字存在，则表示用户已经登录，否则未登录
    if name is not None:
        return jsonify(errno=RET.OK,errmsg='true',data={"name": name})
    else:
        return jsonify(errno=RET.SESSIONERR,errmsg='false')

@api.route("/session", methods=["DELETE"])
def logout():
    '''退出'''
    # 清除session数据
    session.clear()
    return jsonify(erron=RET.OK,errmsg="ok")














